package com.liuche.pictureserver.service.impl;

import com.liuche.pictureserver.common.exception.BizException;
import com.liuche.pictureserver.common.exception.ErrorCode;
import com.liuche.pictureserver.common.resp.BaseResponse;
import com.liuche.pictureserver.common.resp.ResUtils;
import com.liuche.pictureserver.constants.UserConstant;
import com.liuche.pictureserver.enums.UserRoleEnum;
import com.liuche.pictureserver.mapper.UserMapper;
import com.liuche.pictureserver.pojo.domain.UserDO;
import com.liuche.pictureserver.pojo.req.user.UserLoginReqVO;
import com.liuche.pictureserver.pojo.req.user.UserRegistryReqVO;
import com.liuche.pictureserver.pojo.resp.user.UserInfoRespVO;
import com.liuche.pictureserver.service.IUserService;
import com.liuche.pictureserver.utils.BeanUtil;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

/**
 * IUserService实现
 *
 * @author liuche
 */
@Slf4j
@Service
public class UserServiceImpl implements IUserService {
    // 盐值，混淆密码
    private static final String SALT = "liuche";

    @Resource
    private UserMapper userMapper;

    /**
     * 用户注册
     *
     * @param req 注册请求
     * @return 用户id
     */
    @Override
    public Long registry(UserRegistryReqVO req) {
        String userAccount = req.getUserAccount();
        String password = req.getPassword();
        String checkPassword = req.getCheckPassword();

        // 1. 检查是否重复、密码正确性
        if (!password.equals(checkPassword)) {
            throw new BizException(ErrorCode.PARAMS_ERROR, "两次输入密码不一致");
        }

        long count = userMapper.checkAccountExist(userAccount);
        if (count > 0) {
            throw new BizException(ErrorCode.PARAMS_ERROR, "账号重复");
        }

        // 2. 加密
        String encryptPassword = getEncryptPassword(password);

        // 3. 插入数据
        UserDO user = buildBaseInfo(req, userAccount, encryptPassword);
        int num = userMapper.insert(user);
        if (num < 1) {
            throw new BizException(ErrorCode.SYSTEM_ERROR, "注册失败，数据库错误");
        }
        return user.getId();
    }


    /**
     * 用户登录
     *
     * @param req     登录请求
     * @param request 请求头信息
     * @return 结果
     */
    @Override
    public BaseResponse<UserInfoRespVO> login(UserLoginReqVO req, HttpServletRequest request) {
        String userAccount = req.getUserAccount();
        String userPassword = req.getUserPassword();
        // 1. 加密
        String encryptPassword = getEncryptPassword(userPassword);
        // 查询用户是否存在
        UserDO user = userMapper.queryUserByAccountAndPwd(userAccount, encryptPassword);
        // 用户不存在
        if (user == null) {
            log.info("user login failed, userAccount cannot match userPassword");
            throw new BizException(ErrorCode.PARAMS_ERROR, "用户不存在或密码错误");
        }
        // 2. 记录用户的登录态
        request.getSession().setAttribute(UserConstant.USER_LOGIN_STATE, user);
        return ResUtils.success(BeanUtil.toBean(user, UserInfoRespVO.class));
    }

    /**
     * 获取当前登录用户信息
     *
     * @param request 请求信息
     * @return 结果
     */
    @Override
    public UserDO getCurUser(HttpServletRequest request) {
        // 先判断是否已登录
        Object userObj = request.getSession().getAttribute(UserConstant.USER_LOGIN_STATE);
        UserDO currentUser = (UserDO) userObj;
        if (currentUser == null || currentUser.getId() == null) {
            throw new BizException(ErrorCode.NOT_LOGIN_ERROR);
        }
        // 从数据库查询，保证结果准确
        long userId = currentUser.getId();
        currentUser = userMapper.selectById(userId);
        if (currentUser == null) {
            throw new BizException(ErrorCode.NOT_LOGIN_ERROR);
        }
        return currentUser;
    }

    /**
     * 退出登录
     *
     * @param request 请求信息
     * @return 结果
     */
    @Override
    public Boolean logout(HttpServletRequest request) {
        // 先判断是否已登录
        Object userObj = request.getSession().getAttribute(UserConstant.USER_LOGIN_STATE);
        if (userObj == null) {
            throw new BizException(ErrorCode.OPERATION_ERROR, "未登录");
        }
        // 移除登录态
        request.getSession().removeAttribute(UserConstant.USER_LOGIN_STATE);
        return true;
    }

    @Override
    public UserDO queryById(Long userId) {
        return this.userMapper.selectById(userId);
    }


    /**
     * md5加密密码
     *
     * @param userPassword 用户密码
     * @return 结果
     */
    private String getEncryptPassword(String userPassword) {
        return DigestUtils.md5DigestAsHex((SALT + userPassword).getBytes());
    }

    /**
     * 构建用户基本信息
     *
     * @param req             请求信息
     * @param userAccount     账号
     * @param encryptPassword 加密密码
     * @return 结果
     */
    private static UserDO buildBaseInfo(UserRegistryReqVO req, String userAccount, String encryptPassword) {
        UserDO user = new UserDO();
        user.setUserAccount(userAccount);
        user.setUserPassword(encryptPassword);
        user.setUserName(req.getUserName());
        user.setUserRole(UserRoleEnum.USER.getValue());
        return user;
    }
}
